﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using RayDen.Library.Components;
using RayDen.Library.Core.Primitives;
using RayDen.RayEngine.Core.Interface;
using RayDen.RayEngine.Core.Surface;
using RayDen.RayEngine.Core.Types;

namespace RayDen.RayEngine.Data
{
    public class TriangleMeshInfo : BaseTriangleMeshInfo, ITriangleMesh
    {

        
        public GeometryProfile MeshProfile { get; set; }

        public RayEngineMaterial Material { get; set; }

        public SceneDataInfo scene;
        public TriangleMeshInfo(SceneDataInfo scene)
        {
            this.scene = scene;
            MeshProfile = new SurfaceProfile();
        }

      
       [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool TriangleInRange(int triIndex, int delta = 0)
        {
            //return (triIndex <= (EndTriangle) && triIndex >= StartTriangle);

            if (tIndexes == null)
            {
                tIndexes = new HashSet<int>(Enumerable.Range(StartTriangle, EndTriangle - StartTriangle));                
            }
            return tIndexes.Contains(triIndex);
            var start = triIndex != 0 ? StartTriangle + delta : triIndex;
            var end = Math.Max(0, EndTriangle - delta);

            return (triIndex <= (end) && triIndex >= start);
        }

        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        public void InterpolateTriUV(int currentTriangleIndex, float b1, float b2, out UV texCoord)
        {
            var texCoords = scene.GeoData.TexCoords;
            if (scene.GeoData.TexCoords == null
                ||
                scene.Triangles[currentTriangleIndex].v0.TexCoordIndex < 0
                ||
                texCoords.Length < scene.Triangles[currentTriangleIndex].v0.TexCoordIndex)
            {
                texCoord = new UV { U = b1, V = b2 };
            }
            else
            {
                var t0 = texCoords[scene.Triangles[currentTriangleIndex].v0.TexCoordIndex];
                var t1 = texCoords[scene.Triangles[currentTriangleIndex].v1.TexCoordIndex];
                var t2 = texCoords[scene.Triangles[currentTriangleIndex].v2.TexCoordIndex];
                float b0 = 1f - b1 - b2;

                //            return t0 * b1 + t1 * b2 + t2 * b0;
                texCoord = new UV(t0.x * b0 + t1.x * b1 + t2.x * b2, t0.y * b0 + t1.y * b1 + t2.y * b2);

            }
        }

        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        public void InterpolateTriangleNormal(int currentTriangleIndex, float b1, float b2, ref Normal Normal)
        {

            float b0 = 1f - b1 - b2;
            Normal = new Normal(b0 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v0.NormalIndex].x
                                    + b1 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v1.NormalIndex].x
                                        + b2 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v2.NormalIndex].x,
                                b0 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v0.NormalIndex].y
                                    + b1 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v1.NormalIndex].y
                                        + b2 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v2.NormalIndex].y,
                                b0 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v0.NormalIndex].z
                                    + b1 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v1.NormalIndex].z
                                        + b2 * scene.GeoData.Normals[scene.Triangles[currentTriangleIndex].v2.NormalIndex].z);
            //return b0 * n0 + b1 * n1 + b2 * n2;
        }


    }
}